#include "fish.h"
#include <math.h>




//1 3 5
//2 4 6

const GLfloat squareTextureCoords[640] = {
	//0, 0,       // bottom left
	//0, 1,       // top left
	//1, 0,       // bottom right
	//1, 1        // top right
};

#define  PI  3.1415926f

Sky::NType::Bool FishWin::init( myResMgr* resManager,i32 x,i32 y,i32 w,i32 h )
{
	_fish.init(resManager,PointF(-200,200),Vector2F(0,0),1.3f);

	resManager->createFont(&_font,vNull,20,20,20);	

	//_label.create(*resManager,String("abcdefg"),Color(255,0,0),&_font);
	_label.setPosition(-320,200);

	_slider.setRect(200,-200,50,400);

	_water.init(resManager,0,0,0,0);

	GLfloat yy = 0;

	resManager->getApplication()->getTimeCounter().Start(vNull);

	return myWinlet::init(resManager,x,y,w,h);
}

float f = 0;
Sky::MsgStatus FishWin::onPaint( myMsgMgr* mgr,Msg* msg )
{
	TimeCounter& ctr = mgr->getApplication()->getTimeCounter();

	Float dltTime =(Double)ctr.CalTicksElapsed()/ctr.GetTicksPerSecond();

	Point mpos = mgr->getApplication()->getEventMgr().getInput().getMousePoint();

	_water.updateTime(dltTime*400);
	
	//static int posX = -50;
	//posX += 1;

	Sky::Painter* painter = Sky::Painter::castFrom(msg->getMessage());

	_slider.handleInput(mgr->getApplication()->getEventMgr().getInput());

	_fish.addForce(_slider.getForce()/40.0f);

	_fish.getPosition(Vector2F(0,0),dltTime);

	_water.Draw(painter,vNull);

	_fish.onPaint(mgr,msg);

	_slider.Draw(painter,vNull);

	_label.printf(mgr->getApplication()->getResMgr(),painter,Color(255,0,255),&_font,_XT("hell:%3d  %3d   %3d"),mpos.x,mpos.y,_slider.getForce());

	return Sky::vIntercepted;
}

Sky::MsgStatus FishWin::onInput( myMsgMgr* mgr,Msg* event )
{
	return myWinlet::onInput(mgr,event);
}

FishWin::~FishWin()
{

}

Sky::NValue::MsgStatus FishDemo::OnTimer( myMsgMgr* mgr,Msg* msg )
{
	//Message*,MsgStatus
	myWinMsg msg2(&myWinlet::handlePaint,getPainter(),getPainter());
	return getWindowMgr().handleDrawEvent(&getEventMgr(),&msg2);
}

Sky::NType::Bool FishDemo::init()
{
	myApplet::init();

	Handler::Delegate h(this,&FishDemo::OnTimer);

	getEventMgr().createTimer(h,1);

	win1.init(&getResMgr(),0,0,1024,512);

	getWindowMgr().attachFirst(&win1);

	return vTrue;
}

Sky::NType::Vector2F Fish::getResistance()
{
	#define  TIME_FF 1
	Vector2F r;
	if(_pos.y < -32)
	{
		r.x = - _speed.x * 0.8 * TIME_FF;
		r.y = - _speed.y * 0.8 * TIME_FF;
	}
	else if(_pos.y > 0)
	{
		r.x = - _speed.x * 0.1 * TIME_FF;
		r.y = - _speed.y * 0.1 * TIME_FF;
	}
	else
	{
		r.x = - _speed.x * ((_pos.y) / 32 * 0.7 + 0.1) * TIME_FF;
		r.y = - _speed.y * (abs(_pos.y) / 32 * 0.7 + 0.1) * TIME_FF;
	}
	return r;
}

Sky::NType::Vector2F Fish::getBuoyancy()
{
	Vector2F r;
#define  FF 13.0f
	if(_pos.y < -32)
	{
		r.x = 0;
		r.y = FF;
	}
	else if(_pos.y > 0)
	{
		r.x = 0;
		r.y = 0;
	}
	else
	{
		r.x = 0;
		r.y = (abs(_pos.y ) * FF / 32);
	}
	return r;
}

Sky::NType::Void Fish::setPosition( PointF pos )
{
	_pos = pos;
}

Sky::NType::PointF Fish::getPosition( Vector2F f,Double dltTime )
{
	Double t = 0;
	while(t < dltTime)
	{
		t += dltTime / 10 ;
		Vector2F v = getSpeed(f,dltTime / 10);
		_pos.x += v.x * dltTime / 10 * 20;
		_pos.y += v.y * dltTime / 10 * 20;
	}

	return _pos;
}

Sky::NType::Vector2F Fish::getSpeed( Vector2F f,Double dltTime )
{
	_speed.x += dltTime * (f.x + getBuoyancy().x + getResistance().x) / _weight ;

	Double force = (getDepthForce(_pos.y) + _force.y + f.y + getBuoyancy().y + getResistance().y - 9.8f * _weight);

	_speed.y += dltTime * force / _weight;

	return _speed;
}

Sky::NType::Void Fish::init( myResMgr* resManager,PointF pos,Vector2F speed,Float weight )
{
	_pos = pos;
	_speed = speed;
	_weight = weight;
	resManager->createPictFromFile(&_fish_pict,&String(_XT("fish.pvr")));
}

Sky::NType::Float Fish::getDepthForce( Float depth )
{
	if(depth > 0)
		return 0;
	return -depth * 0.02f;
}

Sky::MsgStatus Fish::onPaint( myMsgMgr* mgr,Msg* msg )
{
	Sky::Painter* painter = Sky::Painter::castFrom(msg->getMessage());

	painter->drawPict(Rect(_pos.x,_pos.y,32,32),&_fish_pict);

	painter->blendRect(Rect(_pos.x,_pos.y,32,32),Color(255,255,255,200));
	return vContinue;
}

Sky::NValue::MsgStatus Slider::handleInput( Input& input )
{
	Point pos = input.getMousePoint();
	pos.x -= 320;
	pos.y -= 240;
	if(Helper::isPointInRect(pos,getRect()))
	{
		_force = - pos.y - (getRect()->y + getRect()->h/2);
		return vIntercepted;
	}
	return vContinue;
}

Sky::NType::Void Slider::Draw( Painter* painter,Rect* parentRect )
{
	painter->fillRect(*getRect(),Color(255,255,0,125));
}

Sky::NType::Void Slider::init( i32 x,i32 y,i32 w,i32 h )
{
	setRect(x,y,w,h);
}

#define SCALER 2.0f

Sky::NType::Void Water::init( myResMgr* resManager,i32 x,i32 y,i32 w,i32 h )
{
	resManager->createPictFromFile(&_sea,&String(_XT("sea.pvr")));

	for(int i = 0 ; i < ARRAY_SIZE(water); i ++)
	{
		int idx = i;

		//idx = i % (ARRAY_SIZE(water));

		water[i].p1.x = water[i].p2.x = (idx - (int)ARRAY_SIZE(water)/2) * SCALER;

		water[i].p1.z = water[i].p2.z = 0;

		water[i].p1.y = getWave(i);

		water[i].p2.y = cos((float)idx/10) * 10 - 260;

		water[i].p1.tx = water[i].p2.tx = (idx + 1)%2;
		water[i].p1.ty = 0.9f;
		water[i].p2.ty = 0.1f;
	}
	_curX = 0;
	_trans = 0;
	_indx = 0;
}

Sky::NType::Void Water::move( i32 x )
{
	if(_curX != x)
	{
		_indx += (x - _curX);
		if(_indx >= ARRAY_SIZE(water))
			_indx -= ARRAY_SIZE(water);

		for(int ii = ARRAY_SIZE(water) + _curX; ii < ARRAY_SIZE(water) + x; ++ii)
		{
			int i = ii % ARRAY_SIZE(water);
			water[i].p1.x = water[i].p2.x = (ii - (int)ARRAY_SIZE(water)/2) * SCALER;

			water[i].p1.z = water[i].p2.z = 0;

			water[i].p1.y = getWave(ii);

			water[i].p2.y = cos((float)ii/10) * 10 - 260;

			water[i].p1.tx = water[i].p2.tx = (i + 1)%2;
			water[i].p1.ty = 0.9f;
			water[i].p2.ty = 0.1f;

		}

		_curX = x;
	}
}

Sky::NType::i32 Water::getWave( i32 x )
{
	return sin((float)(x%50)*(PI/50)+PI) * 10 + 10;
}

Sky::NType::Void Water::Draw( Painter* painter,Rect* parentRect )
{
	glBindTexture(GL_TEXTURE_2D, _sea.getTexture());


	glColor4ub(158,207,177,125);

	glEnable(GL_BLEND);

	glBlendFunc(GL_ONE_MINUS_DST_ALPHA , GL_DST_ALPHA);

	glEnableClientState(GL_VERTEX_ARRAY);
	glDisableClientState(GL_COLOR_ARRAY);
	glEnableClientState(GL_TEXTURE_COORD_ARRAY);

	glEnable(GL_TEXTURE_2D);

	glVertexPointer(3, GL_FLOAT, 5*sizeof(GLfloat), water);

	glTexCoordPointer(2, GL_FLOAT, 5*sizeof(GLfloat), &water[0].p1.tx);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	static float sc = 0.0f;
	sc += 0.01;
	float sss = 0.5f + abs(sin(sc) * 0.5f);

	glScalef(1,1,1);

	glTranslatef(f - 200 ,0,0);
	
	glDrawArrays(GL_TRIANGLE_STRIP, _indx * 2 + 2, 2 * ARRAY_SIZE(water) - _indx * 2 - 2);

	glDrawArrays(GL_TRIANGLE_STRIP, 0, _indx * 2);

	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();

	glColor4ub(246,243,200,255);
}

Sky::NType::Void Water::updateTime( Float dltTime )
{
	f -= dltTime;

	_trans = -(int)f;

	move(_trans / SCALER);

	
}
